﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Web;
using viBlog.Classes;
using viBlog.Providers;
using visinia.SmartEngine.Cache;

namespace viBlog.Controllers
{
    /// <summary>
    /// The class to manage the blog post categories
    /// </summary>
    public class CategoryController
    {
        #region CACHE KEYS        
        private const string KEY_CATEGORY_POSTS_COUNT = "viblogCategoryPostsCount";

        #endregion

        /// <summary>
        /// Gets all the Categories
        /// </summary>
        /// <returns>List of all Categories</returns>
        public static List<Category> GetCategories()
        {
            List<Category> list = (List<Category>)DataCache.GetCache("viBlogCategories");
            if (list == null)
            {
                list = FillCategories(viBlogDataProvider.Provider.GetCategories());
                DataCache.SetCache("viBlogCategories", list);
            }
            return list;
        }
                
        /// <summary>
        /// Gets Categories for a specified Post
        /// </summary>
        /// <param name="PostId">Post id</param>
        /// <returns>List of Categories</returns>
        public static List<Category> GetCategories(int PostId)
        {
            string key = string.Format("viBlogCategories_{0}", PostId);
            List<Category> list = (List<Category>)DataCache.GetCache(key);
            if (list == null)
            {
                list = FillCategories(viBlogDataProvider.Provider.GetCategories(PostId));
                DataCache.SetCache(key, list);
            }
            return list;
        }

        /// <summary>
        /// Returns a Specific Category
        /// </summary>
        /// <param name="CategoryId">CategoryId of the Category to Access</param>
        /// <returns>The Category whose CategoryId is given</returns>
        public static Category GetCategory(int CategoryId)
        {
            return GetCategories().Find(p => p.CategoryId == CategoryId);
              
        }

        /// <summary>
        /// Gets the category by its name
        /// </summary>
        /// <param name="CategoryName"></param>
        /// <returns></returns>
        public static Category GetCategory(string CategoryName)
        {            
            return GetCategories().Find(p => (string.Compare(p.Name, CategoryName, true) == 0));
        }

        /// <summary>
        /// Gets the number of posts in the specified category
        /// </summary>
        /// <param name="CategoryId">The category id whose posts count to get</param>
        /// <returns>The count of the posts</returns>
        public static int GetCategoryPostsCount(int CategoryId)
        {
            DataCount data = CategoryPostsCount().Find(p => p.DataId == CategoryId);
            if (data != null)
                return data.Count;
            return 0;
        }

        /// <summary>
        /// The count of the posts in each category
        /// </summary>        
        private static List<DataCount> CategoryPostsCount()
        {
            string key = string.Format(KEY_CATEGORY_POSTS_COUNT);
            List<DataCount> list = (List<DataCount>)DataCache.GetCache(key);
            if (list == null)
            {
                list = FillCategoryPostsCount(viBlogDataProvider.Provider.GetCategoryPostsCount());
                DataCache.SetCache(key, list);
            }
            return list;
        }        

        #region DATA
        public static void ResetCategories(int PostId)
        {
            GetCategories(PostId).ForEach(delegate(Category category)
            {
                RemoveCategory(category.CategoryId, PostId);
            });
            DataCache.DeleteCacheMultiple("viBlogCategor");
        }
        /// <summary>
        /// Associates a category to a post
        /// </summary>
        /// <param name="CategoryId">The category id to associate</param>
        /// <param name="PostId">The post id to be associated</param>
        public static void InsertCategory(int CategoryId, int PostId)
        {
            viBlogDataProvider.Provider.InsertCategory(CategoryId, PostId);
            DataCache.DeleteCacheMultiple("viBlogCategor");
        }

        /// <summary>
        /// Removes the specified category from the post
        /// </summary>        
        public static void RemoveCategory(int CategoryId, int PostId)
        {
            viBlogDataProvider.Provider.RemoveCategory(CategoryId, PostId);
            DataCache.DeleteCacheMultiple("viBlogCategor");
        }

        /// <summary>
        /// Adds a new category
        /// </summary>
        /// <param name="category"></param>
        public static int AddCategory(Category category)
        {
            IDataReader dr = viBlogDataProvider.Provider.AddCategory(category.Name.Trim());            
            int index = 0;
            while (dr.Read())
            {
                if (dr[0] != Convert.DBNull)
                    index = (int)dr[0];
            }
            dr.Close();
            DataCache.DeleteCacheMultiple("viBlogCategor");
            return index;            
        }

        /// <summary>
        /// Update a category
        /// </summary>
        /// <param name="category"></param>
        public static void UpdateCategory(Category category)
        {
            viBlogDataProvider.Provider.UpdateCategory(category.CategoryId, category.Name);
            DataCache.DeleteCacheMultiple("viBlogCategor");
        }

        /// <summary>
        /// Deletes a category
        /// </summary>
        /// <param name="category"></param>
        public static void DeleteCategory(Category category)
        {
            viBlogDataProvider.Provider.DeleteCategory(category.CategoryId);
            DataCache.DeleteCacheMultiple("viBlogCategor");
        }
        #endregion

        #region HELPERS
        private static List<DataCount> FillCategoryPostsCount(IDataReader dr)
        {
            List<DataCount> list = new List<DataCount>();
            while (dr.Read())
            {
                list.Add(ActualReadCategoryPostsCount(dr));
            }
            dr.Close();
            return list;
        }
        private static DataCount ActualReadCategoryPostsCount(IDataReader dr)
        {
            DataCount data = new DataCount();
            if (dr["DataId"] != Convert.DBNull)
                data.DataId = (int)dr["DataId"];
            if (dr["Count"] != Convert.DBNull)
                data.Count = (int)dr["Count"];
            return data;
        }

        private static List<Category> FillCategories(IDataReader dr)
        {
            List<Category> list = new List<Category>();
            while (dr.Read())
            {
                list.Add(ActualRead(dr));
            }
            dr.Close();
            return list;
        }
        private static Category ActualRead(IDataReader dr)
        {
            Category category = new Category();
            if (dr["CategoryId"] != Convert.DBNull)
                category.CategoryId = (int)dr["CategoryId"];
            if (dr["Name"] != Convert.DBNull)
                category.Name = HttpUtility.HtmlEncode((string)dr["Name"]);
            return category;
        }
        #endregion
    }
}
